iT邦幫忙

2024 iThome 鐵人賽

DAY 11
1
JavaScript

TypeScript 初學者也能看的學習指南系列 第 11

TypeScript 初學者也能看的學習指南 11 - 常數列舉(const Enums) & 外部列舉(Ambient Enums)

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20240921/20149362EFue5gfRcP.png

昨天對 Enum 做了基本的介紹,包含 Numeric Enums, String Enums計算成員等,因篇幅限制,把一部分內容補充在這篇~
本篇將會帶你來進一步認識「常數列舉」和「外部列舉」

🚪 文章傳送門 🚪

常數列舉 const Enums

「常數列舉」只能包含 constant enum expression 常數列舉表達式
不論是「字串列舉」還是「數字列舉」都是屬於 constant enum expression 常數列舉表達式,可以使用 +, -, *, /, %, <<, >>, >>>, &, |, ^ 等二元運算子來計算常數,但不能有計算成員!!!(例如:'123'.length, 0 / 0

語法:使用修飾符 const 來定義常數列舉

const enum Set {
  A = 1,
  B = A * 2,
}
const enum Direction {
  Up,
  Down,
  Left,
  Right,
};
let directions = [
  Direction.Up, 
  Direction.Down, 
  Direction.Left, 
  Direction.Right
];
console.log(directions); // [0, 1, 2, 3]
const enum StrDirection {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT", 
}
  1. 如果結是 NaNInfinity,則在編譯階段就會報錯
const enum Nan {
  // a =  0 / 0, // ❌ const' enum member initializer was evaluated to disallowed value 'NaN'.
}
const enum Infinite {
  a = 1 / 0, // ❌ const enum member initializer was evaluated to disallowed value 'Infinity'.
}

移除修飾符 const,就不會報錯了,這是因為普通的列舉可以包含計算結果,即使結果是 NaN 或 Infinity。

enum Nan {
  a =  0 / 0,     // ✅ NaN Pass
}
enum Infinite {
  a = 1 / 0,      // ✅ Infinity Pass
}

外部列舉 Ambient Enums

可以用 declare 修飾符來聲明,它不會生成實際的 JavaScript,只是用來提供編譯時的型別聲明信息,通常用於 .d.ts文件(TypeScript 的聲明文件)

declare enum Ambient {
  Up,
  Down,
  Left,
  Right,
};
let test = [
  Ambient.Up,
  Ambient.Down,
  Ambient.Left,
  Ambient.Right
];
console.log(test); // ❌ ReferenceError: Ambient is not defined...

enums at runtime

enums 在運行時,是一個 JavaScript 物件,這也代表 Enum 在編譯時會被編譯器轉換成物件

enum VerifyResult {
  Pending,  // 0
  Denied,   // 1
  Successful, // 2
};
 
function getVerifyResult (obj: { Pending: number, Successf: number }) {  // ✅ VerifyResult 裡包含了 Pending, Successful
  return obj.Pending;
};
getVerifyResult(VerifyResult);

這例子也告訴我們可以將 enum 作為參數,且也能取得裡面包含的所有成員

VerifyResult 編譯後,結果如下:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var VerifyResult;
(function (VerifyResult) {
    VerifyResult[VerifyResult["Pending"] = 0] = "Pending";
    VerifyResult[VerifyResult["Denied"] = 1] = "Denied";
    VerifyResult[VerifyResult["Successful"] = 2] = "Successful";
})(VerifyResult || (VerifyResult = {}));
;
function getVerifyResult(obj) {
    return obj.Pending;
}
;
getVerifyResult(VerifyResult);
//# sourceMappingURL=example.js.map

enums at compile time

儘管 enums 在 runtime 才是一個真正的 JavaScript 物件,但我們仍可在 compile 中對 key, value 進行操作
編譯時 可以透過 keyof typeof 去取得 enum 中的所有 key,並轉換成 string Union Type (字串聯合型別)

enum LogLevel {
  ERROR,
  WARN,
  INFO,
  DEBUG,
}

type levelKey = keyof typeof LogLevel; // type levelKey = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';

function printLog(key: levelKey, message: string) {
  const value = LogLevel[key];
  if (value <= LogLevel.WARN) {
    console.log(key);      // ERROR
    console.log(value);    // 0
    console.log(message);  // This is a msg
  }
}
printLog("ERROR", "This is a msg");

列舉、元組、陣列 怎麼挑選

項目 列舉 Enum 元組 Tuple 陣列 Array
定義 一組限定範圍的資料集合,如狀態或選項 特定數量和型別的資料,會明確指定哪個位置要哪種型別,是有序性的 儲存多個相同型別的值
使用時機 固定的選項(如天數、狀態) 固定組合的不同型別值時(如座標、excel 欄) 儲存多筆相同型別的元素(如數據列表)
語義清晰性 高(每個成員都有明確名稱) 中(位置重要,但型別可以改變) 低(儲存多筆資料)
範例 enum Status { Active } let a: [string, number] = ['hi', 18] let b: number[] = [1, 2, 3]

每天講的內容有推到 github 上喔

References


上一篇
TypeScript 初學者也能看的學習指南 10 - Enum 列舉
下一篇
TypeScript 初學者也能看的學習指南 12 - 聯合型別 ( | ) 、交集型別 ( & )
系列文
TypeScript 初學者也能看的學習指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言